package remoteService;

import java.awt.BorderLayout;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import concole.*;

public class Server extends JFrame {
	private final String STUDENTFILE = "studentsList.txt";
	private final String TEACHERFILE = "teachersList.txt";
	private final String COURSEFILE = "courseList.txt";
	private final String COURSESELECTEDFILE = "courseSelected.txt";
	private final String STUDENTACCOUNTSFILE = "studentsList.txt";
	private final String TEACHERACCOUNTSFILE = "teacherAccounts.txt";
	JTextArea messageField = new JTextArea();

	/**
	 * public static void main(String[] args) { new Server(); }
	 */

	public Server() {
		setSize(500, 300);
		setLocationRelativeTo(null);
		setTitle("server");
		setLayout(new BorderLayout());
		JScrollPane scrollPane = new JScrollPane(messageField);
		add(scrollPane);
		setVisible(true);

		try {
			ServerSocket serverSocket = new ServerSocket(8000);
			messageField.append("Server starts at " + new Date() + "\n");
			int clientNumber = 1;

			// continually get the new connection with clients
			while (true) {
				Socket s = serverSocket.accept();
				messageField.append("Starting thread for client "
						+ clientNumber);
				InetAddress inetAddress = s.getInetAddress();
				messageField.append(":adressName" + inetAddress.getHostName()
						+ " Adress:" + inetAddress.getHostName() + "\n");
				HandleOne handleOne = new HandleOne(s);
				Thread thread = new Thread(handleOne);
				thread.start();
				clientNumber++;

			}
		} catch (IOException e) {
			System.err.println(e);

		}
	}

	/**
	 * inner class of task to each client
	 * 
	 */
	class HandleOne implements Runnable {
		private Socket s;
		PrintWriter pWriter = null;
		BufferedReader bReader = null;
		Thread thisThread;

		public HandleOne(Socket socket) {
			this.s = socket;
			thisThread = Thread.currentThread();
		}

		@Override
		public void run() {
			boolean hasLogin = false;
			boolean hasRegiste = true;

			// continualy serve client
			while (true) {
				try {
					bReader = new BufferedReader(new InputStreamReader(
							s.getInputStream()));
					pWriter = new PrintWriter(s.getOutputStream());
					String replyString = "";
					String readString = bReader.readLine();
					System.out.println("receiving from client" + readString);
					int cmdInt = CommandHelper.getOperand(readString);
					String opcodeString = CommandHelper.getOpcode(readString);
					// String opcodeString="";
					String[] opcodeStrings = opcodeString.split("!");
					switch (cmdInt) {
					case 10:
						replyString = IOHelper.findOneRecord(0,
								"loginAccounts.txt", opcodeString);
						System.out.println("create replyString" + replyString);
						break;
					case 11:
						replyString = IOHelper.findOneRecord(0,
								"teacherAccounts.txt", opcodeString);
						break;
					case 12:
						replyString = IOHelper.findOneRecord(0,
								"studentAccounts.txt", opcodeString);

						break;
					case 21:
						replyString = null;

						IOHelper.writeBackToFile("LoginAccounts.txt", "admin"
								+ " " + opcodeString);
						break;
					case 22:
						replyString = IOHelper.getAllFile(opcodeString);
						break;
					case 23:
						readString = null;
						IOHelper.deleteOneLine(opcodeStrings[0].trim(),
								Integer.parseInt(opcodeStrings[1].trim()));
						break;
					case 31:
						Course oldCourse = new Course(opcodeStrings[0]);
						Course newCourse = new Course(opcodeStrings[1]);
						boolean ifCnumChange = opcodeStrings[2].equals("T");
						boolean ifTChange = opcodeStrings[3].equals("F");
						doTask31(oldCourse, newCourse, ifCnumChange, ifTChange);
						break;
					case 32:
						replyString = doTask32(opcodeString);
						break;
					case 33:
						doTask33(new Course(opcodeString));
						break;

					case 34:
						replyString = doTask34(opcodeString);
						break;
					case 35:
						Course oldCourse2 = new Course(opcodeStrings[0]);
						Course newCourse2 = new Course(opcodeStrings[1]);
						doTask35(oldCourse2, newCourse2);
						break;
					case 36:
						System.out.println("Start case36:" + opcodeString);
						replyString = doTask36(opcodeString);
						break;
					case 37:
						replyString = doTask37(opcodeString);
						break;
					case 38:
						replyString = doTask38(opcodeString);
						break;
					case 39:
						doTask39(opcodeString);
						break;
					case 41:// processNetGetCourseInfo
						replyString = IOHelper.findOneRecord(0,
								"courseList.txt", opcodeString);
						break;
					case 42:// processNetHasRight
						replyString = IOHelper.findOneRecord(0, 1,
								"courseSelected.txt", opcodeStrings[0],
								opcodeStrings[1]);
						break;
					case 43:// processNetGetScore
						break;
					case 44:// processNetSelectC
						break;
					case 45:// proceessNetQuit
						break;
					case 46:// processNetShowAllCourse
						break;
					default:

						break;
					}

					pWriter.write(replyString);
					pWriter.flush();
					pWriter.close();
					System.out.println("The reply is " + replyString);
				} catch (Exception e) {
					// TODO: handle exception
					System.err.println(e);

				} finally {
					try {
						pWriter.close();
						bReader.close();
						// s.close();
					} catch (IOException e2) {
						// TODO: handle exception
						System.out.println(e2);
					}

				}
			}
		}

		private void doTask39(String opcodeString) {
			// TODO Auto-generated method stub
			String[] tostoreStrings = opcodeString.split("#");
			for (int i = 0; i < tostoreStrings.length; i++) {
				IOHelper.addOneLine("Scores.txt", tostoreStrings[i]);
			}
		}

		private String doTask38(String teacherNum) {
			// TODO Auto-generated method stub
			String resultString = IOHelper.findAllRegionMatches(3,
					"CourseList.txt", teacherNum);
			System.out.println(resultString);

			return resultString;
		}

		private String doTask37(String courseNum) {
			// TODO Auto-generated method stub
			String string = IOHelper.findAllMatchInfo(1, "Scores.txt",
					courseNum);

			return string;
		}

		private String doTask36(String teacherNum) {
			// TODO Auto-generated method stub
			/*
			 * System.out.println("getIOhelper"+courseNum); String string =
			 * IOHelper.findAllMatchInfo(0, "courseSelected.txt", courseNum);
			 */
			String string = IOHelper.findAllRegionMatches(3, "CourseList.txt",
					teacherNum);
			string = string.replaceAll("\n", "!");
			System.out.println("getIOhelper\n" + string);

			return string;
		}

		private void doTask35(Course oldCourse2, Course newCourse2) {
			// TODO Auto-generated method stub
			IOHelper.replaceOneRecord("courseList.txt",
					oldCourse2.toStoreString(), newCourse2.toStoreString());
		}

		private String doTask34(String opcodeString) {
			// TODO Auto-generated method stub
			String reply = IOHelper.findOneRecord(0, "courseList.txt",
					opcodeString);
			return reply;
		}

		private void doTask33(Course course) {
			// TODO Auto-generated method stub
			IOHelper.addOneLine("courseList.txt", course.toStoreString());
			/*
			 * refresh the file of teacher and add the courseNum to the specific
			 * record
			 */
			for (int i = 0; i < course.teachers.size(); i++) {
				IOHelper.addToLineEnd("teachersList.txt", course.teachers
						.get(i).getNum(), 0, course.getCourseNumber());
			}
		}

		private String doTask32(String numString) {
			// TODO Auto-generated method stub
			String resultString = "";
			String[] strings = null;
			StringBuffer bf = new StringBuffer();
			if (numString.contains("&")) {
				strings = numString.split("&");
				for (int i = 0; i < strings.length; i++) {
					bf.append((new Teacher(strings[i]).setNameFromFile()) + "&");
				}
			} else {
				bf.append((new Teacher(numString).setNameFromFile()));
			}
			resultString = bf.toString();
			if (resultString.trim().endsWith("&")) {
				resultString = resultString.substring(0,
						resultString.lastIndexOf("&"));
			}
			System.out.println(resultString);
			return resultString;
		}

		private void doTask31(Course oldCourse, Course newCourse,
				boolean ifCnumChange, boolean ifTChange) {
			// TODO Auto-generated method stub
			if (ifCnumChange) {
				for (int i = 0; i < oldCourse.teachers.size(); i++) {
					IOHelper.replaceOneTermOfLine("teachersList.txt", oldCourse
							.getCourseNumber(), newCourse.getCourseNumber(),
							oldCourse.teachers.get(i).getNum(), 2, 0);
				}
			}
			if (ifTChange) {
				for (int i = 0; i < oldCourse.teachers.size(); i++) {
					IOHelper.removeOneTermFromLine("teachersList.txt",
							newCourse.getCourseNumber(), oldCourse.teachers
									.get(i).getNum(), 2, 0);
				}
				for (int i = 0; i < newCourse.teachers.size(); i++) {
					IOHelper.addToLineEnd("teachersList.txt",
							newCourse.teachers.get(i).getNum(), 0,
							newCourse.getCourseNumber());
				}
			}
		}
	}
}
